package com.cloudpolice.door.controller;

import	java.util.ArrayList;

import java.io.File;
import java.lang.Double;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.cloudpolice.door.constant.ProviderEnum;
import com.cloudpolice.door.dto.FaceLogDTO;
import com.cloudpolice.door.feignInterface.EquipmentInterFace;
import com.cloudpolice.door.feignInterface.PicAndAiPicInterFace;
import com.cloudpolice.door.feignInterface.UploadFileInterFace;
import com.cloudpolice.door.feignInterface.VerifaceInterFace;
import com.cloudpolice.door.model.EquipmentModel;
import com.cloudpolice.door.model.EquipmentSiteModel;
import com.cloudpolice.door.model.FaceLogRecordMainModel;
import com.cloudpolice.door.model.InPutParam.*;
import com.cloudpolice.door.service.FaceLogService;
import com.cloudpolice.door.unit.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import lh.model.ResultVO;
import lh.model.ResultVOPage;
import lh.toolclass.LhClass;
import lh.units.ResultStruct;
import lombok.extern.log4j.Log4j2;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.stream.Collectors;

/**
 * @author ：梁昊，后端工程师：flyman5，前端工程师：孙耀
 * @create 2020-02-28 12:17
 * @function
 * @editLog
 */
@Log4j2
@RestController
@RequestMapping("/faceLogController")
@Api(value = "门禁记录聚合层", description = "处理门禁记录聚合层")
@RefreshScope
public class FaceLogController {
    @Autowired
    FaceLogService faceLogService;
    @Autowired
    GetPropertiesClass getPropertiesClass;
    @Autowired
    EquipmentInterFace equipmentInterFace;
    @Autowired
    Gson gson;
    @Autowired
    RabbitMQUtil rabbitMQUtil;
    @Autowired
    VerifaceInterFace verifaceInterFace;
    @Autowired
    UploadFileInterFace uploadFileInterFace;
    @Autowired
    PicAndAiPicInterFace picAndAiPicInterFace;
    /**
     * 获取图片中的小脸还是大脸（0-小脸，1-大脸）
      */
    @Value("${get.image.faces}")
    private String isFace;
    /**
     * 图片临时存放路径
     */
    @Value("${temp.image.path}")
    private String imagePath;

    /**
     * 得到门禁机抓拍记录根据，方法ID：SE20200306111753767C749C696B55C
     *
     * @param personId 表inf_face_log,字段名personId:人员ID（居民，物业人员，警务人员)
     * @param page     当前页数
     * @param limit    每页条数
     * @return 抓拍记录
     */
    @ApiOperation(value = "得到门禁机抓拍记录根据,方法ID：SE20200306111753767C749C696B55C", notes = "抓拍记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "useId", value = "人员ID（居民，物业人员，警务人员)", dataType = "String", required = true),
            @ApiImplicitParam(name = "page", value = "当前页数", dataType = "String"),
            @ApiImplicitParam(name = "limit", value = "每页条数", dataType = "String")
    })
    @PostMapping("/SelectFaceLogByPersonId")
    public ResultVOPage SelectFaceLogByPersonId(@RequestParam(value = "useId") String personId
            , @RequestParam(value = "page", defaultValue = "1") int page
            , @RequestParam(value = "limit", defaultValue = "10") int limit) {
        personId = personId == null ? personId : personId.trim();

        PageHelper.startPage(page, limit);
        List<FaceLogRecordMainModel> faceLogRecordMainModels = faceLogService.SelectFaceLogByPersonId(personId);
        PageInfo pageInfo = new PageInfo<>(faceLogRecordMainModels, limit);
        return ResultStruct.successPage(faceLogRecordMainModels, pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal());
    }

    /**
     * 根据设备SN号和MAC得到,设备是否允许登录
     *
     * @param sn  表inf_equipment,字段名id:设备SN号(不可重复主键)
     * @param mac 表inf_equipment,字段名mac:mac地址
     * @return 设备基本信息
     */
    @ApiOperation(value = "根据设备SN号和MAC得到,设备是否允许登录", notes = "设备是否允许登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sn", value = "设备SN号(不可重复主键)", dataType = "String", required = true, defaultValue = "sn123456"),
            @ApiImplicitParam(name = "mac", value = "设备mac(不可重复)", dataType = "String", required = true, defaultValue = "EO-D5-5E-96-89-3B"),
    })
    @PostMapping("/EquipmentLogBySnAndMac")
    public ResultVO EquipmentLogBySnAndMac(@RequestParam(value = "sn") String sn
            , @RequestParam(value = "mac") String mac) {
        final ResultVO resultVO = equipmentInterFace.SelectEquipmentBySnAndMac(sn, mac);
        return resultVO;
    }

    /**
     * 静态库人员录入接口
     *
     * @param imageId  图片ID
     * @param personId 人员ID
     * @param personType 录入人员类型，默认传11
     * @return 录入结果
     */
    @ApiOperation("静态库人员录入接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "imageId", value = "图片ID", required = true),
            @ApiImplicitParam(name = "personId", value = "人员ID", required = true),
            @ApiImplicitParam(name = "personType", value = "录入人员类型，5-在逃人员，6-警综库人员，11-人证采集库", defaultValue = "11")
    })
    @PostMapping(value = "/personnelEntry")
    public ResultVO personnelEntry(@RequestParam(value = "imageId") String imageId,
                                   @RequestParam(value = "personId") String personId,
                                   @RequestParam(value = "personType") String personType) {
        // 1、从静态资源站点获取图片字符串
        String result = uploadFileInterFace.selectFileStreamById(imageId, false, true);
        if (StringUtils.isEmpty(result)) {
            return ResultStruct.error("personnelEntry-从静态资源站点获取图片流失败", ResultVO.class);
        }
        result = StringUtils.split(result, ",")[1];

        // 2、上传图片，获取图片ID和图片位置
        ResultVO resultVO = verifaceInterFace.imageUpload(result, "true", "0");
        if (resultVO.getCode() != 0) {
            return ResultStruct.error("personnelEntry-imageUpload, " + resultVO.getMsg(), ResultVO.class);
        }

        JSONObject jsonObject = JSONObject.fromObject(resultVO.getData());
        // 源图片地址
        String sourceImage = jsonObject.getString("sourcePath");
        // 删除临时文件
        ImageUtil.deleteTempFile(new File(sourceImage));
        log.info("personnelEntry-上传图片接口返回数据：" + jsonObject.toString());
        jsonObject = jsonObject.getJSONObject("data");

        // 图片中人脸个数
        int faces = jsonObject.getInt("faces");
        if (faces != 1) {
            resultVO = new ResultVO();
            resultVO.setCode(1);
            resultVO.setMsg(" 此图片无人脸信息或有多张人脸");
            return ResultStruct.error(resultVO.getMsg(), ResultVO.class);
        }

        // 深目返回的图片ID
        String thirdImageId = jsonObject.getString("id");

        // 4、录入静态库人员（只有一个人脸）
        resultVO = verifaceInterFace.enterStaffInfo(thirdImageId, personType, null, null, null, null);
        if (resultVO.getCode() != 0) {
            return ResultStruct.error("personnelEntry-enterStaffInfo, " + resultVO.getMsg(), ResultVO.class);
        }

        result = resultVO.getData().toString().replaceAll("null", "\"\"");
        jsonObject = JSONObject.fromObject(result);
        log.info("录入静态库人员接口返回数据：" + jsonObject.toString());
        JSONArray jsonArray = jsonObject.getJSONArray("data");
        String thirdId = "";
        for (Object o : jsonArray) {
            jsonObject = (JSONObject) o;
            // 接口返回的人员id
            thirdId = jsonObject.getString("id");
        }

        // 5、将相关信息发送到MQ（第三方人员ID，人员ID，算法提供方）
        jsonObject.clear();
        jsonObject.put("thirdId", thirdId);
        jsonObject.put("personId", personId);
        jsonObject.put("verifaceId", ProviderEnum.INTELLIFUSION.getValue());
        if (rabbitMQUtil.send(jsonObject)) {
            log.info("静态库人员相关信息已发送至MQ！");
        }

        return ResultStruct.success(jsonObject);
    }

    /**
     * AI在线实时比对接口
     *
     * @param imageId 图片ID
     * @param pid     平台ID
     * @return 比对结果
     */
    @ApiOperation("AI在线实时比对接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sn", value = "设备号", required = true),
            @ApiImplicitParam(name = "imageId", value = "图片ID", required = true),
            @ApiImplicitParam(name = "pid", value = "平台ID，1-云天励飞，当前仅支持1", required = true)
    })
    @PostMapping(value = "/onlineCompare")
    public ResultVO onlineCompare(@RequestParam(value = "sn") String sn,
                                  @RequestParam(value = "imageId") String imageId,
                                  @RequestParam(value = "pid") String pid) {
        // 1、从静态资源站点获取图片字符串
        String result = uploadFileInterFace.selectFileStreamById(imageId, false, true);
        if (StringUtils.isEmpty(result)) {
            return ResultStruct.error("onlineCompare-从静态资源站点获取图片流失败", ResultVO.class);
        }
        result = StringUtils.split(result, ",")[1];

        // 2、上传图片，获取图片ID和图片位置
        ResultVO resultVO = verifaceInterFace.imageUpload(result, "true", "0");
        if (resultVO.getCode() != 0) {
            return ResultStruct.error("onlineCompare-imageUpload, " + resultVO.getMsg(), ResultVO.class);
        }

        JSONObject jsonObject = JSONObject.fromObject(resultVO.getData());
        // 源图片地址
        String sourceImage = jsonObject.getString("sourcePath");
        log.info("onlineCompare-上传图片接口返回数据：" + jsonObject.toString());
        jsonObject = jsonObject.getJSONObject("data");

        // 图片中人脸个数
        int faces = jsonObject.getInt("faces");
        if (faces <= 0) {
            resultVO = new ResultVO();
            resultVO.setCode(1);
            resultVO.setMsg(" 此图片无人脸信息");
            return ResultStruct.error(resultVO.getMsg(), ResultVO.class);
        }
        // 第三方图片ID
        String id = jsonObject.getString("id");

        // 2、根据大图id获取所有小图信息(获取所有人脸ID)
        resultVO = verifaceInterFace.getDetectImage(id);
        if (resultVO.getCode() != 0) {
            return ResultStruct.error("onlineCompare-getDetectImage, " + resultVO.getMsg(), ResultVO.class);
        }
        // 若目录不存在，则创建文件目录
        ImageUtil.mkdir(imagePath);

        Map<Integer, String> faceImage = new HashMap<>(10);
        Map<Integer, String> coords = new HashMap<>(10);
        StringBuilder faceIds = new StringBuilder();
        JSONObject json, rect;
        int i = 1, width, height;
        StringBuilder coord, path;
        String filePath, fileName;
        jsonObject = JSONObject.fromObject(resultVO.getData());
        JSONArray jsonArray = jsonObject.getJSONArray("data");
        for (Object o : jsonArray) {
            jsonObject = (JSONObject) o;

            // 人脸库位置
            json = jsonObject.getJSONObject("json");

            // 获取人脸图（0-人脸小图，1-人脸大图）
            if ("0".equals(isFace)) {
                rect = json.getJSONObject("Rect");
            } else {
                rect = json.getJSONObject("FaceImageRect");
            }

            // 计算人脸的宽度和高度
            width = rect.getInt("right") - rect.getInt("left");
            height = rect.getInt("bottom") - rect.getInt("top");

            // 图片路径
            path = new StringBuilder();
            fileName = RandomUtil.generateString(31) + i + ".jpg";
            filePath = path.append(imagePath).append(File.separator)
                    .append(fileName).toString();

            // 截取人脸图片
            ImageUtil.cutPicture(sourceImage, filePath, rect.getInt("left"), rect.getInt("top"),
                    width, height);
            faceImage.put(i, filePath + "-" + fileName);

            coord = new StringBuilder();
            coord.append(rect.getInt("left")).append(",").append(rect.getInt("top")).append(",")
                    .append(rect.getInt("right")).append(",").append(rect.getInt("bottom"));
            coords.put(i, coord.toString());
            i++;

            // 人脸ID
            faceIds.append(jsonObject.getString("id")).append(",");
        }
        // 在图片上画人脸框
        path = new StringBuilder();
        fileName = RandomUtil.generateString(32) + ".jpg";
        filePath = path.append(imagePath).append(File.separator)
                .append(fileName).toString();
        ImageUtil.drawPicture(sourceImage, filePath, coords);

        // 3、将所有处理后的图片上传至静态资源库
        byte[] data = ImageUtil.image2byte(filePath);
        // 上传画框图片，成功后删除本地临时图片
        resultVO = uploadFileInterFace.multiPartFileUploadByByteArray(data, fileName, "");
        if (resultVO.getCode() != 0) {
            return ResultStruct.error("onlineCompare-uploadAloneFile, " + resultVO.getMsg(), ResultVO.class);
        }
//        ImageUtil.deleteTempFile(new File(imageId));
        String faceBasePicId = ((List)resultVO.getData()).get(0).toString();

        // 上传人脸小图，成功后删除本地临时图片
        for (Object value : faceImage.values()) {
            data = ImageUtil.image2byte(value.toString().split("-")[0]);
            resultVO = uploadFileInterFace.multiPartFileUploadByByteArray(data, value.toString().split("-")[1], "");
            if (resultVO.getCode() != 0) {
                return ResultStruct.error("onlineCompare-uploadAloneFile, " + resultVO.getMsg(), ResultVO.class);
            }
//            ImageUtil.deleteTempFile(new File(imageId));
        }
        faceImage.clear();

        // 4、根据人脸ID在静态库中进行通用检索
        faceIds = new StringBuilder(faceIds.substring(0, faceIds.length() - 1));
        String startTime = "2019-01-01 00:00:00";
        String endTime = DateUtil.now();
        resultVO = verifaceInterFace.searchFaceByPage(faceIds.toString(), "5", startTime, endTime, "1", "10000");
        if (resultVO.getCode() != 0) {
            return ResultStruct.error("onlineCompare-searchFaceByPage, " + resultVO.getMsg(), ResultVO.class);
        }

        // 解析返回json数据
        jsonObject = JSONObject.fromObject(resultVO.getData());
        if (jsonObject.getInt("total") == 0) {
            return ResultStruct.error("没有检索到对应的人脸信息", ResultVO.class);
        }
        jsonArray = jsonObject.getJSONArray("data");
        double score = 0d;
        Map<String, Double> map = new HashMap<>(8);
        for (Object o : jsonArray) {
            jsonObject = (JSONObject) o;
            // 人员ID
            id = jsonObject.getString("id");
            // 相似度
            score = jsonObject.getDouble("score");
            map.put(id, score);
        }

        // 按value进行降序，取出第一个元素，就是相似度最高的结果
        Map<String, Double> sorted = map.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));
        id = sorted.keySet().stream().findFirst().get();
        score = sorted.entrySet().stream().findFirst().get().getValue();

        // 5、查询AI人员关联信息
        log.info("人员ID：" + id + ", 相似度：" + score);
        resultVO = picAndAiPicInterFace.getPicAndAiPic(null, id, pid);
        log.info("查询人脸关联人员信息：" + resultVO.toString());
        if (resultVO.getCode() != 0) {
            return ResultStruct.error("onlineCompare-getPicAndAiPic, " + resultVO.getMsg(), ResultVO.class);
        }
        if (StringUtils.isEmpty(resultVO.getData())){
            return ResultStruct.error("未查询到AI人员关联信息", ResultVO.class);
        }
        jsonObject = JSONObject.fromObject(resultVO.getData());
        String personId = jsonObject.getString("id");

        // 6、将相关数据返回，并发送至MQ
        String fid = LhClass.getFaceMain(Short.parseShort(getPropertiesClass.getPort()));
        FaceLogBaseInsertInParam faceLog = new FaceLogBaseInsertInParam();
        faceLog.setId(fid);
        faceLog.setPersonId(personId);
        faceLog.setFaceBasePicId(faceBasePicId);
        faceLog.setOpenType(0);
        faceLog.setAiType(pid);
        faceLog.setDoorTime(new Date());
        faceLog.setRemark("AI在线比对");
        faceLog.setBasePicId(imageId);
        faceLog.setSn(sn);
        faceLog.setAiClass(true); // true-在线，false-离线
        String faceLogContent = JSON.toJSONString(faceLog);

        List<FaceLogSubBaseInsertInParam> faceLogSubs = new ArrayList<> ();
        FaceLogSubBaseInsertInParam faceLogSub = null;
        String[] rects = null; i=0;
        String[] face = faceIds.toString().split(",");
        for (Object value : coords.values()) {
            faceLogSub = new FaceLogSubBaseInsertInParam();
            rects = value.toString().split(",");
            faceLogSub.setLeftUp(Integer.parseInt(rects[0]));
            faceLogSub.setLeftDown(Integer.parseInt(rects[1]));
            faceLogSub.setRigthUp(Integer.parseInt(rects[2]));
            faceLogSub.setRigthDown(Integer.parseInt(rects[3]));
            faceLogSub.setSmallFacePicId(face[i]);
            faceLogSubs.add(faceLogSub);
            i++;
        }
        String faceLogSubContent = JSON.toJSONString(faceLogSubs);

        String content = faceLogContent + "-" + faceLogSubContent;
        log.info("在线比对相关信息：" + content);
        if (rabbitMQUtil.send2(content)) {
            log.info("在线比对相关信息已发送至MQ！");
        }

        jsonObject.clear();
        jsonObject.put("sn", sn); // 设备号
        jsonObject.put("platformId", pid); // 平台ID
        jsonObject.put("personId", personId); // 人员ID
        jsonObject.put("thirdId", id); // 第三方人员ID
        jsonObject.put("fid", fid); // 开门记录ID
        jsonObject.put("similarity", score); // 相似度

        return ResultStruct.success(jsonObject);
    }

    /**
     * 更新门禁机开门状态接口
     *
     * @param fid 开门记录
     * @return 比对结果
     */
    @ApiOperation("更新门禁机开门状态接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fid", value = "人员ID", required = true)
    })
    @PostMapping(value = "/updateFaceLogById")
    public ResultVO updateFaceLogById (@RequestParam(value = "fid") String fid) {
        // 根据开门记录ID查询门禁机开门记录
        FaceLogInsertInParam faceLog = faceLogService.selectFaceLogById(fid);
        if (faceLog == null) {
            return ResultStruct.error("未查询到门禁机开门记录", ResultVO.class);
        }

        // 更新门禁机开门记录状态
        faceLog.setStopSign(1);
        faceLog.setRemark("开门成功");
        int count = faceLogService.updateFaceLogById(faceLog);

        return ResultStruct.success("", count);
    }

    /**
     * 根据相关参数查询开门记录，方法ID：SE2020042414101536621D40C5B9F8F
     *
     * @param id 主键ID
     * @param personName 人员姓名
     * @param mobile 手机号
     * @param openType 开门方式（0:刷脸，1:RFID卡，2:二维码，3:远程开门）
     * @param sn 设备SN号
     * @param communityId 场所ID（小区ID、学校ID等 )
     * @param periodId 场所区域ID（小区区域ID、学校区域ID等）
     * @param buildId 楼栋ID
     * @param unitId 单元ID
     * @param accessId 通道ID
     * @param startTime 查询开始时间
     * @param endTime 查询结束时间
     * @return 根据相关参数查询开门记录
     */
    @ApiOperation(value = "根据相关参数查询开门记录,方法ID：SE2020042414101536621D40C5B9F8F", notes = "根据相关参数查询开门记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "String"),
            @ApiImplicitParam(name = "personName", value = "人员姓名", dataType = "String"),
            @ApiImplicitParam(name = "mobile", value = "手机号", dataType = "String"),
            @ApiImplicitParam(name = "openType", value = "开门方式（0:刷脸，1:RFID卡，2:二维码，3:远程开门）", dataType = "String"),
            @ApiImplicitParam(name = "sn", value = "设备SN号", dataType = "String"),
            @ApiImplicitParam(name = "communityId", value = "场所ID（小区ID、学校ID等 )", dataType = "String"),
            @ApiImplicitParam(name = "periodId", value = "场所区域ID（小区区域ID、学校区域ID等）", dataType = "String"),
            @ApiImplicitParam(name = "buildId", value = "楼栋ID", dataType = "String"),
            @ApiImplicitParam(name = "unitId", value = "单元ID", dataType = "String"),
            @ApiImplicitParam(name = "accessId", value = "通道ID", dataType = "String"),
            @ApiImplicitParam(name = "startTime", value = "查询开始时间，格式：yyyy-MM-dd HH:mm:ss", dataType = "Date", required = true),
            @ApiImplicitParam(name = "endTime", value = "查询结束时间，格式：yyyy-MM-dd HH:mm:ss", dataType = "Date", required = true)
    })
    @PostMapping("/selectFaceLogsByParam")
    public ResultVO selectFaceLogsByParam(@RequestParam(value = "id", required = false) String id
            , @RequestParam(value = "personName", required = false) String personName
            , @RequestParam(value = "mobile", required = false) String mobile
            , @RequestParam(value = "openType", required = false) String openType
            , @RequestParam(value = "sn", required = false) String sn
            , @RequestParam(value = "communityId", required = false) String communityId
            , @RequestParam(value = "periodId", required = false) String periodId
            , @RequestParam(value = "buildId", required = false) String buildId
            , @RequestParam(value = "unitId", required = false) String unitId
            , @RequestParam(value = "accessId", required = false) String accessId
            , @RequestParam(value = "startTime") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime
            , @RequestParam(value = "endTime") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date  endTime) {
        id = id == null ? id : id.trim();
        personName = personName == null ? personName : personName.trim();
        mobile = mobile == null ? mobile : mobile.trim();
        sn = sn == null ? sn : sn.trim();
        communityId = communityId == null ? communityId : communityId.trim();
        periodId = periodId == null ? periodId : periodId.trim();
        buildId = buildId == null ? buildId : buildId.trim();
        unitId = unitId == null ? unitId : unitId.trim();
        accessId = accessId == null ? accessId : accessId.trim();
        openType = openType == null ? "0" : openType.trim();
//        Date startDate = DateUtil.parse(startTime, DateUtil.formatPattern);
//        Date endDate = DateUtil.parse(endTime, DateUtil.formatPattern);

        FaceLogSelectInParam faceLogSelectInParam = new FaceLogSelectInParam();
        faceLogSelectInParam.setId(id);
        faceLogSelectInParam.setPersonName(personName);
        faceLogSelectInParam.setMobile(mobile);
        faceLogSelectInParam.setOpenType(Integer.parseInt(openType));
        faceLogSelectInParam.setSn(sn);
        faceLogSelectInParam.setCommunityId(communityId);
        faceLogSelectInParam.setPeriodId(periodId);
        faceLogSelectInParam.setBuildId(buildId);
        faceLogSelectInParam.setUnitId(unitId);
        faceLogSelectInParam.setAccessId(accessId);
        faceLogSelectInParam.setStartTime(startTime);
        faceLogSelectInParam.setEndTime(endTime);
        List<FaceLogDTO> list = faceLogService.selectFaceLogsByParam(faceLogSelectInParam);
        return ResultStruct.success(list, list.size());
    }

    @ApiOperation(value = "测试门禁机上传功能", notes = "影响条数")
    @PostMapping("/testFace")
    public ResultVO testFace() {
        FaceLogBaseInsertInParam faceLogBaseInsertInParam = new FaceLogBaseInsertInParam();
        faceLogBaseInsertInParam.setSn("sn123456");
        faceLogBaseInsertInParam.setBasePicId("BasePic1");
        faceLogBaseInsertInParam.setPersonId("PersonId");
        faceLogBaseInsertInParam.setPersonType(0);
        faceLogBaseInsertInParam.setFaceBasePicId("FacePic1");
        faceLogBaseInsertInParam.setCardId("CarId");
        faceLogBaseInsertInParam.setOpenType(0);
        faceLogBaseInsertInParam.setAiType("AIName1");
        faceLogBaseInsertInParam.setDoorTime(new Date());
        faceLogBaseInsertInParam.setRemark("remark1");
        List<FaceLogSubBaseInsertInParam> faceLogSubBaseInsertInParams = new ArrayList<>();
        //非二维码方式，才上传从表记录，卫立星，请注意！！！
        if (faceLogBaseInsertInParam.getOpenType() < 3) {
            for (int i = 0; i < 4; i++) {
                FaceLogSubBaseInsertInParam faceLogSubBaseInsertInParam = new FaceLogSubBaseInsertInParam();
                faceLogSubBaseInsertInParam.setLeftDown(1);
                faceLogSubBaseInsertInParam.setLeftUp(1);
                faceLogSubBaseInsertInParam.setReality((float) 0.02);
                faceLogSubBaseInsertInParam.setRigthDown(2);
                faceLogSubBaseInsertInParam.setRigthUp(2);
                faceLogSubBaseInsertInParam.setSmallFacePicId("SamllFacePicId");
                faceLogSubBaseInsertInParam.setStandard((float) 0.81);
                faceLogSubBaseInsertInParam.setSuccess(1);
                faceLogSubBaseInsertInParam.setHatSign(1);
                faceLogSubBaseInsertInParam.setMaskSign(1);
                faceLogSubBaseInsertInParam.setGlassesSign(1);
                faceLogSubBaseInsertInParam.setScarfSign(1);
                faceLogSubBaseInsertInParams.add(faceLogSubBaseInsertInParam);
            }
        }
        return insertIniFaceLog(faceLogBaseInsertInParam, faceLogSubBaseInsertInParams);
    }

    @ApiOperation(value = "测试门禁机上传功能", notes = "影响条数")
    @PostMapping("/testFaceString")
    public ResultVO testFaceString() {
        FaceLogBaseInsertInParam faceLogBaseInsertInParam = new FaceLogBaseInsertInParam();
        faceLogBaseInsertInParam.setSn("sn123456");
        faceLogBaseInsertInParam.setBasePicId("BasePic1");
        faceLogBaseInsertInParam.setPersonId("PersonId");
        faceLogBaseInsertInParam.setPersonType(0);
        faceLogBaseInsertInParam.setFaceBasePicId("FacePic1");
        faceLogBaseInsertInParam.setCardId("CarId");
        faceLogBaseInsertInParam.setOpenType(0);
        faceLogBaseInsertInParam.setAiType("AIName1");
        faceLogBaseInsertInParam.setDoorTime(new Date());
        faceLogBaseInsertInParam.setRemark("remark1");
        List<FaceLogSubBaseInsertInParam> faceLogSubBaseInsertInParams = new ArrayList<>();
        //非二维码方式，才上传从表记录，卫立星，请注意！！！
        if (faceLogBaseInsertInParam.getOpenType() < 3) {
            for (int i = 0; i < 4; i++) {
                FaceLogSubBaseInsertInParam faceLogSubBaseInsertInParam = new FaceLogSubBaseInsertInParam();
                faceLogSubBaseInsertInParam.setLeftDown(1);
                faceLogSubBaseInsertInParam.setLeftUp(1);
                faceLogSubBaseInsertInParam.setReality((float) 0.02);
                faceLogSubBaseInsertInParam.setRigthDown(2);
                faceLogSubBaseInsertInParam.setRigthUp(2);
                faceLogSubBaseInsertInParam.setSmallFacePicId("SamllFacePicId");
                faceLogSubBaseInsertInParam.setStandard((float) 0.81);
                faceLogSubBaseInsertInParam.setSuccess(1);
                faceLogSubBaseInsertInParam.setHatSign(1);
                faceLogSubBaseInsertInParam.setMaskSign(1);
                faceLogSubBaseInsertInParam.setGlassesSign(1);
                faceLogSubBaseInsertInParam.setScarfSign(1);
                faceLogSubBaseInsertInParams.add(faceLogSubBaseInsertInParam);
            }
        }
        final String s = gson.toJson(faceLogBaseInsertInParam);
        final String s1 = gson.toJson(faceLogSubBaseInsertInParams);
        System.out.println(s);
        System.out.println(s1);
        return insertFaceLog(s, s1);
    }

    @ApiOperation(value = "增加门禁记录（MQ发送端）", notes = "影响条数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mainFaceLog", value = "门禁记录主表", dataType = "String", required = true)
            , @ApiImplicitParam(name = "subFaceLogList", value = "门禁记录从表", dataType = "String", required = true)
    })
    @PostMapping("/insertFaceLog")
    public ResultVO insertFaceLog(@RequestParam(value = "mainFaceLog") String mainFaceLog
            , @RequestParam(value = "subFaceLogList") String subFaceLogList) {
        if (mainFaceLog == null || mainFaceLog.isEmpty()) {
            return ResultStruct.error("主表记录不能为空!", ResultVO.class, null);
        }
        List<FaceLogSubBaseInsertInParam> faceLogSubBaseInsertInParams = new ArrayList<>();
        FaceLogBaseInsertInParam faceLogBaseInsertInParam = gson.fromJson(mainFaceLog, FaceLogBaseInsertInParam.class);
        if (subFaceLogList != null && !subFaceLogList.isEmpty()) {
            final List list = gson.fromJson(subFaceLogList, List.class);
            for (Object row :
                    list) {
                FaceLogSubBaseInsertInParam faceLogSubBaseInsertInParam = gson.fromJson(row.toString(), FaceLogSubBaseInsertInParam.class);
                if (faceLogSubBaseInsertInParam != null) {
                    faceLogSubBaseInsertInParams.add(faceLogSubBaseInsertInParam);
                }
            }
        }
        if (faceLogBaseInsertInParam == null) {
            return ResultStruct.error("主表记录不能为空!", ResultVO.class, null);
        }
        if (faceLogBaseInsertInParam.getOpenType() == 0 && faceLogSubBaseInsertInParams == null || faceLogSubBaseInsertInParams.isEmpty()) {
            return ResultStruct.error("刷脸方式下，从表记录不能为空!", ResultVO.class, null);
        }
        return insertDownDoorRecord(faceLogBaseInsertInParam, faceLogSubBaseInsertInParams);
    }

    @ApiOperation(value = "增加门禁记录（MQ发送端）,方法ID：IN20200228120816952C2633BFF5C41", notes = "影响条数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "faceLogBaseInsertInParam", value = "Face_Log对象", dataType = "FaceLogBaseInsertInParam", required = true)
            , @ApiImplicitParam(name = "faceLogSubBaseInsertInParams", value = "Face_Log_child对象", dataType = "FaceLogSubBaseInsertInParam", paramType = "query")
    })
    @PostMapping("/insertIniFaceLog")
    public ResultVO insertIniFaceLog(@RequestBody FaceLogBaseInsertInParam faceLogBaseInsertInParam
            , @RequestBody(required = false) List<FaceLogSubBaseInsertInParam> faceLogSubBaseInsertInParams) {
        if (faceLogBaseInsertInParam == null) {
            return ResultStruct.error("主表记录不能为空!", ResultVO.class, null);
        }
        if (faceLogBaseInsertInParam.getOpenType() == 0 && faceLogSubBaseInsertInParams == null || faceLogSubBaseInsertInParams.isEmpty()) {
            return ResultStruct.error("刷脸方式下，从表记录不能为空!", ResultVO.class, null);
        }
        return insertDownDoorRecord(faceLogBaseInsertInParam, faceLogSubBaseInsertInParams);
    }

    /**
     * 离线、在线，首次提交数据库，主表方法
     *
     * @param faceLogBaseInsertInParam
     * @param afterSign
     * @return
     */
    private FaceLogInsertInParam getFaceLogInsertInParam(FaceLogBaseInsertInParam faceLogBaseInsertInParam
            , boolean afterSign) {
        String mainKey = LhClass.getFaceMain(Short.valueOf(getPropertiesClass.getPort()));//这里引用架包中的生成主键方法
        FaceLogInsertInParam faceLogInsertInParam = new FaceLogInsertInParam();
        faceLogInsertInParam.setId(mainKey);
        faceLogInsertInParam.setSn(faceLogBaseInsertInParam.getSn());
        faceLogInsertInParam.setBasePicId(faceLogBaseInsertInParam.getBasePicId());
        faceLogInsertInParam.setPersonId(faceLogBaseInsertInParam.getPersonId());
        faceLogInsertInParam.setFaceBasePicId(faceLogBaseInsertInParam.getFaceBasePicId());
        faceLogInsertInParam.setPersonType(faceLogBaseInsertInParam.getPersonType());
        faceLogInsertInParam.setRemark(faceLogBaseInsertInParam.getRemark());
        faceLogInsertInParam.setStopSign(0);
        faceLogInsertInParam.setAiClass(afterSign);

        if (afterSign) {
            faceLogInsertInParam.setOpenType(0);
            faceLogInsertInParam.setAiAfterType(getPropertiesClass.getAiArithmeticName());
            faceLogInsertInParam.setDoorTime(new Date());
        } else {
            faceLogInsertInParam.setCardId(faceLogBaseInsertInParam.getCardId());
            faceLogInsertInParam.setOpenType(faceLogBaseInsertInParam.getOpenType());
            faceLogInsertInParam.setAiType(faceLogBaseInsertInParam.getAiType());
            faceLogInsertInParam.setDoorTime(faceLogBaseInsertInParam.getDoorTime());
        }
        return faceLogInsertInParam;
    }

    /**
     * 离线、在线，首次提交数据库，从表方法
     *
     * @param faceLogSubBaseInsertInParam
     * @param index
     * @param mainId
     * @return
     */
    private FaceLogSubInsertInParam getFaceLogSubInsertInParam(FaceLogSubBaseInsertInParam faceLogSubBaseInsertInParam
            , int index
            , String mainId) {
        FaceLogSubInsertInParam faceLogSubInsertInParam = new FaceLogSubInsertInParam();
        faceLogSubInsertInParam.setId(LhClass.getFaceSub(Short.valueOf(getPropertiesClass.getPort())));
        faceLogSubInsertInParam.setMainId(mainId);
        faceLogSubInsertInParam.setSortNo(index);

        faceLogSubInsertInParam.setLeftDown(faceLogSubBaseInsertInParam.getLeftDown());
        faceLogSubInsertInParam.setLeftUp(faceLogSubBaseInsertInParam.getLeftUp());
        faceLogSubInsertInParam.setReality(faceLogSubBaseInsertInParam.getReality());
        faceLogSubInsertInParam.setRigthDown(faceLogSubBaseInsertInParam.getRigthDown());
        faceLogSubInsertInParam.setRigthUp(faceLogSubBaseInsertInParam.getRigthUp());
        faceLogSubInsertInParam.setSmallFacePicId(faceLogSubBaseInsertInParam.getSmallFacePicId());
        faceLogSubInsertInParam.setStandard(faceLogSubBaseInsertInParam.getStandard());
        faceLogSubInsertInParam.setSuccess(faceLogSubBaseInsertInParam.getSuccess());
        faceLogSubInsertInParam.setHatSign(faceLogSubBaseInsertInParam.getHatSign());
        faceLogSubInsertInParam.setMaskSign(faceLogSubBaseInsertInParam.getMaskSign());
        faceLogSubInsertInParam.setGlassesSign(faceLogSubBaseInsertInParam.getGlassesSign());
        faceLogSubInsertInParam.setScarfSign(faceLogSubBaseInsertInParam.getScarfSign());
        return faceLogSubInsertInParam;
    }

    private ResultVO insertDownDoorRecord(FaceLogBaseInsertInParam faceLogBaseInsertInParam
            , List<FaceLogSubBaseInsertInParam> faceLogSubBaseInsertInParams) {
        FaceLogInsertInParam faceLogInsertInParam = getFaceLogInsertInParam(faceLogBaseInsertInParam, false);

        List<FaceLogSubInsertInParam> faceLogSubInsertInParams = new ArrayList<>();
        if (faceLogSubBaseInsertInParams != null) {
            int index = 0;
            for (FaceLogSubBaseInsertInParam faceLogSubBaseInsertInParam :
                    faceLogSubBaseInsertInParams) {
                FaceLogSubInsertInParam faceLogSubInsertInParam = getFaceLogSubInsertInParam(faceLogSubBaseInsertInParam
                        , index++
                        , faceLogInsertInParam.getId());
                faceLogSubInsertInParams.add(faceLogSubInsertInParam);
            }
        }
        int resultCount = faceLogService.insertAllFaceLog(faceLogInsertInParam, faceLogSubInsertInParams);
        if (resultCount > 0) {
            UpdateFaceLogThread updateFaceLogThread = new UpdateFaceLogThread(faceLogInsertInParam);
            updateFaceLogThread.run();
            return ResultStruct.success("上传成功", resultCount);
        } else {
            return ResultStruct.error("上传失败", ResultVO.class, null);
        }
    }

    private class UpdateFaceLogThread implements Runnable {
        private FaceLogInsertInParam faceLogInsertInParam;

        private UpdateFaceLogThread(FaceLogInsertInParam faceLogInsertInParam) {
            this.faceLogInsertInParam = faceLogInsertInParam;
        }

        @Override
        public void run() {
            String errorInfo = "未找到冗余信息：";
            boolean updateSign = true;
            FaceLogInsertInParam faceLogInsertInParamNew = new FaceLogInsertInParam();
            faceLogInsertInParamNew.setId(faceLogInsertInParam.getId());
            System.out.println("getPersonId:" + faceLogInsertInParam.getPersonId());
            faceLogInsertInParamNew.setSex("0");
            faceLogInsertInParamNew.setMobile("13972342314");
            faceLogInsertInParamNew.setPersonName("PersonName1");
            faceLogInsertInParamNew.setBlackType("BlackType");
            faceLogInsertInParamNew.setBlackTag("BlackTag");

            if (updateSign) {
                final ResultVO resultVOEquip = equipmentInterFace.SelectEquipmentBySn(faceLogInsertInParam.getSn(), false);
                updateSign = updateSign && (resultVOEquip.getCode() == 0 ? true : false);
                if (updateSign) {
                    final EquipmentModel equipmentModel = gson.fromJson(resultVOEquip.getData().toString(), EquipmentModel.class);
                    faceLogInsertInParamNew.setEquipmentName(equipmentModel.getEquipmentName());
                    faceLogInsertInParamNew.setEquipmentType(equipmentModel.getEquipmentType());
                } else {
                    errorInfo += resultVOEquip.getMsg();
                }
            }

            if (updateSign) {
                final ResultVO resultVOEquipSite = equipmentInterFace.selectEquipmentSiteBySn(faceLogInsertInParam.getSn());
                updateSign = updateSign && (resultVOEquipSite.getCode() == 0 ? true : false);
                if (updateSign) {
                    final List list = gson.fromJson(resultVOEquipSite.getData().toString(), List.class);
                    for (Object row :
                            list) {
                        final EquipmentSiteModel equipmentSiteModel = gson.fromJson(row.toString(), EquipmentSiteModel.class);
                        switch (equipmentSiteModel.getRoomType()) {
                            case 0:
                                faceLogInsertInParamNew.setCommunityId(equipmentSiteModel.getSiteId());//场所
                                break;
                            case 1:
                                faceLogInsertInParamNew.setPeriodId(equipmentSiteModel.getSiteId());//区域
                                break;
                            case 2:
                                faceLogInsertInParamNew.setBuildId(equipmentSiteModel.getSiteId());//楼栋
                                break;
                            case 3:
                                faceLogInsertInParamNew.setUnitId(equipmentSiteModel.getSiteId());//单元
                                break;
                            default:
                                faceLogInsertInParamNew.setAccessId(equipmentSiteModel.getSiteId());//通道
                                break;
                        }
                    }
                } else {
                    errorInfo += resultVOEquipSite.getMsg();
                }
            }
            faceLogInsertInParamNew.setCommunityName("ComName");
            faceLogInsertInParamNew.setPeriodName("PeroidName");
            faceLogInsertInParamNew.setBuildName("BuildName");
            faceLogInsertInParamNew.setUnitName("UnitName");
            faceLogInsertInParamNew.setAccessName("AccessName1");

            faceLogInsertInParamNew.setLatitude((float) 23.3245324);
            faceLogInsertInParamNew.setLongitude((float) 3435.4564);


            if (updateSign) {
                faceLogInsertInParamNew.setRemark("ThreadOver");
            } else {
                faceLogInsertInParamNew.setRemark(errorInfo);
            }

            faceLogService.updateFaceLogById(faceLogInsertInParamNew);
        }

    }

}
